package geektime.spring.web.context;

import geektime.spring.web.foo.FooConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * <p>
 * fooContext  (父ApplicationContext)
 * bean：
 * testBeanX("foo")
 * testBeanY("foo")
 * <p>
 * barContext  (子ApplicationContext)
 * bean：
 * testBeanX("bar")
 * <p>
 * fooAspect()  -->  一个拦截，拦截所有“testBean*”的bean，然后打个日志
 * 分别放开applicationContext.xml(子) 或 FooConfig.java(父) 中的这个拦截。
 * 也就是实验一下，AOP定义在父中能否拦截子的bean，或者AOP定义在子中能否拦截父的bean
 * <p>
 * 结论:
 * 1、子上下文中没有找到的bean，会去父上下文中找
 * 2、父\子上下文中的AOP，只能增强(代理)到自己上下文中的bean
 * 3、想增强哪一层，就在哪一层定义AOP
 * 4、如果是通用的，就定义在上层(父)上下文，然后下层(子)上下文`<aop:aspectj-autoproxy/>`
 * (也就是哪层想增强(被代理)首先要启用aspect，其次在本层找AOP，找不到就去上层找)
 */
@SpringBootApplication
@Slf4j
public class ContextHierarchyDemoApplication implements ApplicationRunner {

    public static void main(String[] args) {
        SpringApplication.run(ContextHierarchyDemoApplication.class, args);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {

        ApplicationContext fooContext = new AnnotationConfigApplicationContext(FooConfig.class);
        // 这里是传入 父ApplicationContext = fooContext
        // 最终也就是  barContext extends fooContext
        ClassPathXmlApplicationContext barContext = new ClassPathXmlApplicationContext(
                new String[]{"applicationContext.xml"}, fooContext);
        TestBean bean = fooContext.getBean("testBeanX", TestBean.class);
        bean.hello();

        log.info("=============");

        bean = barContext.getBean("testBeanX", TestBean.class);
        bean.hello();

        bean = barContext.getBean("testBeanY", TestBean.class);
        bean.hello();
    }
}
